        TITL DAI FIRMWARE D620-D78F  V1.0  Rev.1
        ORG   :D620
*
*
*
**************************
* COMPLETE KEYBOARD SCAN *
**************************
*
* Initialises a complete keyboard scan,
* independent of the KNSCAN flag, and performs it.
*
* Exit: All registers preserved.
*
KFSCAN  PUSH  PSW
        PUSH  B
        PUSH  D
        PUSH  H
        LXI   H,:02B9   Addr KNSCAN pointer
        MVI   M,:00     Enable complete scan
        PUSH  H
        CALL  :D59A     Scan keyboard and store
 REM result in circ.buffer
        POP   H
        DCR   M         Scan for BREAK only
        JMP   :CB56     Popall; return
*
**********************************
* GET ASCII VALUE OF KEY PRESSED *
**********************************
*
* Calculates address in ASCII table in ROM and gets
* ASCII value of the key pressed. The result is
* stored in the 4-bye circular buffer KLIND.
*
* Entry: A:  Keycode of scanned row (7 bits only).
*        B:  FF when REPT pressed; else 00.
*        C:  Number of row.
*        DE: Address in MAP2.
*        HL: Address in MAP1.
* Exit:  BCDEHL preserved; AF corrupted.
*
TKEY    PUSH  B
        MVI   B,:07     Check which key in row is
TKY10   RAR             pressed; calculate offset
        CC    :D63F     Get ASCII value; store it
 REM in KLIND
        DCR   B
        JNZ   :D635     Next column
        POP   B
        RET
*
* GET KEY-ASCII VALUE AND STORE IT:
*
SINKEY  RST   1         Get ASCII-value from ROM-
        DATA  :12       table and store it in KLIND
        RET
*
*******************************
* OUTPUT TO RS232 IF REQUIRED *
*******************************
*
* Checks if output is to RS232. If positive,
* output is performed.
*
* Entry: Byte to be transmitted in A.
*
TOUTSE  PUSH  PSW
        LDA   :0131     Get output direction
        ORA   A         Check if RS232 output
        JNZ   :DD8C     Abort if not
        POP   PSW
        JMP   :DD94     Output to RS232
*
******************************************
* GET ASCII-VALUE OF CHARACTER IN BUFFER *
******************************************
*
* Routine is not used.
*
* The Ascii-value of a character is stored in
* KLIND. Afterwards, Bank select is restored.
*
LD67    CALL  :E93F     (3) Ascii-value in KLIND
        POP   PSW       A contains POROM
        CALL  :D808     Update PORO and POROM
        POP   PSW
        POP   H
        RET
*
************************************
* parts of RUN 'RANDOMISE' (0E40C) *
************************************
*
*RMI15
MPT39   DCR   A
        JNZ   :D658     Again till A=0
        MOV   A,M       Get contents FD00
        XRA   E
        RET
*
* Entry: L = 0.
*
MPT38   LDA   :01C1     Get keyb.scan time count
 REM (0, 1 or 2)
        RRC
        RRC             A= 0, #40 or #80
        MOV   E,A       in E
        MOV   B,L       )
        MOV   C,L       ) BC=0
        RET
*
************************************
* WRITE 2 BLOCKS + TRAILER ON TAPE *
************************************
*
* Entry: HL:    Startaddress 1st block.
*        Stack: Length 2nd block.
*               Startaddress 2nd block.
*
MPT13   LXI   D,:0001   Length 1st block = 1
        CALL  :02C8     Write 1st block
        POP   D         Get length 2nd block
        POP   H         Get startaddr. 2nd block
        CALL  :02C8     Write 2nd block
        CALL  :02CB     Write trailer
        ORA   A
        RET
*
********************************
* LOADA: EVALUATE PROGRAM NAME *
********************************
*
* The program name is evaluated. Selection of
* ROM bank 1 is prepared.
*
MPT14   CALL  :D687     Evaluate program name
        LDA   :0040     Get POROM
        ORI   :40       Prepare selection ROMbank 1
        RET
*
******************
* OPEN READ FILE *
******************
*
MPT18   PUSH  D
        CALL  :02CE     Open READ file
        POP   D
        RET
*
*********************************
* EVALUATE A STRING EXPRESSSION *
*********************************
*
* A string expression is evaluated. Eventually,
* the Heap entry is cleared if the string was
* temporarily on Heap.
*
* Exit: DE preserved, BC updated.
*       HL points after string
*
MPT15   PUSH  D
        CALL  :E791     (0) Eval. string expr.
 REM evt. clear Heap entry
        POP   D
        RET
*
*******************
* CURSOR HANDLING *
*******************
*
* Load the cursor pointers with the address, the
* colour and the contents of a new cursor address.
*
* Entry: HL: New cursor address.
*        D:  The colour byte of this location.
*        E:  The contents of this location.
* Exit:  HL and DE exchanged; ABCF preserved.
*
SPT00   SHLD  :0072     Store cursor address
        XCHG
        SHLD  :0076     Store cursor addr.contents
        RET
*
************************
* OUTPUT ONE CHARACTER *
************************
*
* Output direction depending on OTSW.
* This routine is useable for all data output
* functions in machine language programs.
*
* Entry: Character for output in A.
* Exit:  All registers preserved.
*
MPT31   PUSH  PSW
        CALL  :DD60     Output character in A.
        POP   PSW
        RET
*
        DATA  :FF
*
************************************************
* KEYB. SCANNING: UPDATE POINTER OUTPUT BUFFER *
************************************************
*
* Updates the pointer to the circular output
* buffer #02BA-#02BD.
*
* Entry: HL: KLIOU.
* Exit:  HL: Updated KLIOU.
*        AF corrupted. BCDE preserved.
*
KPTRU   INX   H         Incr. KLIOU
        MOV   A,L       Lobyte into A
        CPI   :BE       Buffer full?
        RNZ             Quit if not
        LXI   H,:02BA   Else: wrap around
        RET
*
******************************************
* KEYBOARD SCANNING: CHECK IF NEW INPUTS *
******************************************
*
* Returns a flag if BREAK has been pressed or if
* there is a character available.
*
* Entry: No conditions.
* Exit:  BCDEHL preserved.
*        A: Difference KLIIN and KLIOU. 
*        CY=1: Break pressed.
*        CY=0, Z=1: No inputs.
*        CY=0, Z=0: New input available.
*
*ASKKEY
BREAK   PUSH  H
 REM
* If suspended:
 REM
        LXI   H,:02C4   Addr break pntr
        MOV   A,M
        DCR   A
        CPI   :FE       Test if not 0 or FF
        JC    :D6B9     Abort if break: CY=1
*
        LHLD  :02C0     Get KLIOU
        LDA   :02BE     Get KLIIN
        SUB   L         New keys pressed?
        STC
        CMC             CY=0
OTK10   POP   H
        RET
*
******************
* INPUT SCANNING *
******************
*
* Gets input from keyboard or DINC, depending on
* INSW (0296).
*
* FGETC: Gets a character, even if keyboard
*        scanning is turned off.
*  GETC: Returns a flag if break, and sets break
*        accepted. Returns also a flag if a
*        character is available.
*
* Exit: CY=1: Break pressed.
*       Z=1:  No inputs. Then A=0.
*       Else: Character in A.
*
FGETC   CALL  :D620     Complete keyboard scan
GETC    JMP   :D1DB     Check input keyb/DINC;
 REM scan for new keys pressed
MPR29   JC    :D6D4     Jump if Break pressed.
        RZ              No new input or buffer full
 REM
* If inputs:
 REM
        PUSH  H
        LHLD  :02C0     Get addr pntr output buffer
        MOV   A,M       Get ASCII char in A
        PUSH  PSW
        CALL  :D69C     Update pntr
        POP   PSW
        SHLD  :02C0     Re-instate KLIOU
        POP   H
        RET             CY=0
 REM
* If Break pressed:
 REM
GTC10   MVI   A,:FF     Flag 'break accepted'
        STA   :02C4     Scan for break only
        RET             CY=1
*
*********************
* WAIT FOR SPACEBAR *
*********************
*
* Wait until spacebar (or break) is pressed.
*
* Entry: None.
* Exit:  CY=1: Break pressed.
*        CY=0: Space in A.
*        BCDEHL preserved.
*
WSPACE  CALL  :D6BB     Input scanning
        RC              Abort if BREAK pressed
        CPI   :20       Check if spacebar
        JNZ   :D6DA     Wait for space bar
        ORA   A
        RET
*
*************************
* part of LOADA (1EE0F) *
*************************
*
MPT20   XTHL            Orig. DE in HL, free RAM
 REM pntr on stack
        CALL  :DE14     Compare DE-HL
        JNC   :D6ED     If DE<=HL
        XCHG
RLA15   MOV   B,D       ) Lowest value in BC
        MOV   C,E       )
        POP   D
        POP   H
        XTHL
        JMP   :EE4C     (1) Continu
*
*****************************************
* CHECK SUFFICIENT SCREEN RAM AVAILABLE *
* PREPARE SELECTION SPLIT MODE          *
*****************************************
*
SPT01   STC             CY=1
        LHLD  :0090     Get end area splitting mode
        CALL  :E5A6     (2) Ask for temporary area
        LXI   H,:E5A0   (2) Startaddr table screen
 REM parameters split modes
        RET
*
******************************************
* CHANGE FROM SPLIT TO FULL GRAPHIC MODE *
******************************************
*
SSM20   CALL  :D6F5     Check suff. screen RAM
        JMP   :E485     (2) Change split to full
*
*****************************************
* CHECK SUFFICIENT SCREEN RAM AVAILABLE *
* PREPARE FULL GRAPHICS MODE            *
*****************************************
*
SPTA2   CALL  :D6F5     Check suff. screen RAM
        LXI   H,:E59A   (2) Startaddr table screen
 REM parameters full graph.modes
        RET
*
******************************
* SET UP CURRENT SCREEN MODE *
******************************
*
SMA20   POP   D
        POP   PSW
SMA30   LDA   :009D     Get current screen mode
        ORA   A
        RAR             Split or all-graph mode ?
        CALL  :E539     (2) Set up screen mode
        JMP   :E43C     (2) Pop PSW, ret
*
*************************
* STOP LOADING PROGRAMS *
*************************
*
* Entry: HL: New end symbol table.
* Exit:  All registers preserved.
*
MPT11   SHLD  :02A3     Store end symtab
        JMP   :02D4     Stop loading
*
*****************************
* INIT. WRITING FILE LEADER *
*****************************
*
* Procedure depends on saving in program or not.
*
MPT21   PUSH  H
        LHLD  :0100     Get start current line
        MOV   A,H
        ORA   L         0 if not during run
        POP   H
        JNZ   :D414     If SAVE during run
        JMP   :D40C     Write file leader
*
******************************************
* INIT. SOUNDGENERATOR, GIC, START HEAP, *
* MOVE CASSETTE VECTORS, GET DCE INPUTS  *
******************************************
*
MPT00   CALL  :D8A6     Init. sound generator
        CALL  :D795     Transfer cassette vectors
        LXI   H,:02EC
        RST   1         Init. GIC: get evt. inputs
        DATA  :0C       from DCE-bus (bootstrap)
        SHLD  :029B     Set HEAP start
        RET
*
        DATA  :02       (not used)
*
********************************************
* part of RUN A VARIABLE REFERENCE (0E95A) *
********************************************
*
MPT49   CALL  :E96D     (0) Run VARPTR
        POP   D
        RET
*
        DATA  :DD       (not used)
*
*************************************************
* SET INPUT DIRECTION, LOAD SOUND + KEYB TIMERS *
*************************************************
*
* Part of 'stack interrupt' (D9E2).
*
MPT30   STA   :0135     Set input direction
        CALL  :D99D     Reload keyboard timer
        JMP   :D9A3     Reload sound timer, ret
*
*******************************
* DATA OUTPUT ROUTINE 'DOUTC' *
*******************************
*
* Part of DD70.
* On #02DD, an jump to an user determined output
* routine can be written. As default, a RET is
* on this address.
*
OTC30   POP   PSW       Output char in A
        JMP   :02DD     Goto user DOUTC
*
********************
* CHECK BREAK FLAG *
********************
*
* Part of 'scan keyboard' (D59A).
*
* Entry: Address 'break' flag in BC.
* Exit:  BCDEHL preserved, AF corrupted.
*
MPT28   LDAX  B         Get KBRFL
        INR   A
        RNZ             Quit if it was <> FF
        STAX  B         KBRFL=0: No recent break
        RET
*
***************************
* SOUND INTERRUPT (RST 3) *
***************************
*
* Called periodically every few milliseconds.
* Adjust the volume for the sound channels and
* approaches the correct frequency if necessary.
*
* Saves all registers + interrupt mask.
* Enables only clock and sound interrupts.
* Sound interrupt timer is re-loaded and sound
* control blocks are executed.
*
* Entry: HL must already be saved on stack.
* Exit:  All registers preserved.
*        Bank select is restored.
*
SNTMP   PUSH  PSW
        PUSH  B
        PUSH  D
        LDA   :005F     Get current int. mask
        PUSH  PSW       and save it
        MVI   A,:84     )
        STA   :005F     ) Enable clock and sound
        STA   :FFF8     ) interrupts only
        EI
        CALL  :D9A3     Reload sound timer
        LDA   :0040     Get POROM
        PUSH  PSW       and save it
        ANI   :3F
        ORI   :40       Select ROM bank 1
        STA   :0040     Set POROM
        STA   :FD06     and PORO
        CALL  :EE6E     (1) Execute SCB('s)
        POP   PSW
        STA   :0040     Re-instate old ROM bank
        STA   :FD06     and save it
        JMP   :D9CD     Restore int. mask; ret
*
************************
* FAILURE DURING ROPEN *
************************
*
MPT54   DCR   B
        INR   B
        JNZ   :D7DE     If file type byte <>0:
 REM Run error
        POP   PSW
        RET
*
************************************
* CHECK IF LOAD DURING RUN PROGRAM *
************************************
*
* Entry: C: 00 if load during run, else it is FF.
*        A: File type byte.
* Exit:  ABCDEHL preserved.
*
MPT24   DCR   C
        INR   C         Check C
        RZ              Abort if during run
        JMP   :D7EB     Display file type byte
*
*
*
        UNL
ASKKEY  EQU BREAK
RMI15   EQU MPT39
        LST
        END
